/**!
 * FileName: jq.validform.js
 * Copyright (c) 2011-2012 sotee, http://www.sotee.com
 * Usage: http://home.blueidea.com/apps.php?do=bxna&ac=view&feedid=12443
 */
/**!
 * -CLASS-
 * @name validform
 * @description 基于jQuery的通用表单验证插件。
 * @syntax JQ插件，使用 [ $(".demoform").validform(初始化参数) ] 直接调用
 * @version 2.0
 * @since 1.0
 */
(function($) {
	var errorobj = null, msghidden = true, msgobj,
		//默认提示文字
		tipmsg = {
			w: "请输入正确信息！",
			r: "通过信息验证！",
			c: "正在检测信息…",
			s: "请填入信息！",
			v: "所填信息没有经过验证，请稍后…",
			p: "正在提交数据…"
		},
		pwdInfo = [
			"密码太短", "很不安全", "不安全", "一般", "安全的", "非常安全",
			"red", "#f8523d", "#fde45c", "#dff05d", "#cbe757", "#75c343"
		],
	creatMsgbox = function() {
		if($("#validform_msg").length!==0) return false;
		//提示信息框
		msgobj = $([
			'<div id="validform_msg"><div class="validform_title">提示信息',
			'<a class="validform_close" href="javascript:void(0);">&chi;</a>',
			'</div><div class="validform_info"></div><div class="iframe">',
			'<iframe frameborder="0" scrolling="no" height="100%" width="100%">',
			'</iframe></div></div>'
		].join('')).appendTo("body");
		msgobj.find("a.validform_close").click(function() {
			msgobj.hide();
			msghidden = true;
			errorobj && errorobj.focus().addClass("validform_error");
			return false;
		}).focus(function() {
			this.blur();
		});
		$(window).bind("scroll resize", function() {
			if(!msghidden) {
				var w = $(window), d = document, dd = d.documentElement,
					t = (w.height()-msgobj.height()) / 2;
				msgobj.animate({
					left: (w.width() - msgobj.width()) / 2,
					top: (dd.scrollTop ? dd.scrollTop : d.body.scrollTop) + (t > 0 ? t : 0)
				}, {
					duration: 400,
					queue: false
				});
			}//Endif
		});
	},
	//密码强度测试
	getPasswordStrength = function(password) {
		return 0
		// if password bigger than 5 give 1 point
		+ +( password.length > 5 )
		// if password has both lower and uppercase characters give 1 point
		+ +( /[a-z]/.test(password) && /[A-Z]/.test(password) )
		// if password has at least one number and at least 1 other character give 1 point
		+ +( /\d/.test(password) && /\D/.test(password) )
		// if password has a combination of other characters and special characters give 1 point
		+ +( /[!,@,#,$,%,^,&,*,?,_,~,-,(,)]/.test(password) && /\w/.test(password) )
		// if password bigger than 12 give another 1 point (thanks reddit)
		+ +( password.length > 12 )
	};
	//初始化页面的表单验证控件
	$.fn.validform= function(option) {
		option = $.extend({}, $.fn.validform.sn.defaults, option);
		var defaults = {};
		this.each(function() {
			var T = $(this),
				//防止表单按钮双击提交两次
				posting = false;
			//tipInfo是表单元素的默认提示信息,这是点击清空效果;
			T.find("[tipInfo]").each(function() {
				var T = $(this), defaultvalue = T.attr("tipInfo"),
					altercss = T.attr("altercss");
				T.focus(function() {
					$(this).val() == defaultvalue
						&& ($(this).val(''), altercss && $(this).removeClass(altercss));
				}).blur( function() {
					$.trim($(this).val()) === ''
						&& ($(this).val(defaultvalue), altercss && $(this).addClass(altercss));
				});
			});
			//密码强度验证
			T.find("[dataType=strength]").bind("keyup", function() {
				var p = getPasswordStrength(this.value), obj = $($(this).attr("pointer")).children();
				obj.first().text("安全程度：" + pwdInfo[p])
					.css("color", pwdInfo[6 + p]).next().width(p * 20 + "%")
			});
			//绑定blur事件;
			T.find("[dataType]").blur(function() {
				var M = $(this),
					flag = $.fn.validform.sn.checkform(M, T, option.tipType, "hide");
				if(!flag || typeof flag != "boolean") {
					//如果是radio, checkbox, select则不需再执行下面的代码;
					typeof flag != "boolean" && M.removeClass("validform_error");
					return false;
				}//Endif
				if(!(flag = $.fn.validform.sn.regcheck(M.attr("dataType"), M.val()))) {
					if(M.attr("ignore") === "ignore"
						&& (M.val() === "" || M.val() === M.attr("tipInfo"))) {
						option.tipType == 2 && M.parent().next()
							.find(".validform_checktip").removeClass()
							.addClass("validform_checktip").text(M.attr("tipInfo"));
						return (flag = true);
					}//Endif
					errorobj = M;
					$.fn.validform.sn.showmsg(M.attr("errTip") || tipmsg.w,
						//当tipType = 1的情况下，传入"hide"则让提示框不弹出,
						//  tipType = 2的情况下附加参数“hide”不起作用
						option.tipType, { obj: M }, "hide");
				}else if(M.attr("ajaxurl")) {
					var inputobj = M;
					inputobj.attr("valid", tipmsg.c);
					$.fn.validform.sn.showmsg(tipmsg.c, option.tipType, {
						obj: inputobj, type: 1 }, "hide");
					$.ajax({
						type: "POST",
						url: inputobj.attr("ajaxurl"),
						data: "param=" + M.val(),
						dataType: "text",
						success: function(s) {
							if(s == "y") {
								inputobj.attr("valid", "true");
								$.fn.validform.sn.showmsg(tipmsg.r, option.tipType, {
									obj: inputobj, type: 2 }, "hide");
							}else {
								inputobj.attr("valid", s);
								errorobj = inputobj;
								$.fn.validform.sn.showmsg(s, option.tipType, { obj: inputobj });
							}//Endif
						}
					});
				}else {
					errorobj = null;
					$.fn.validform.sn.showmsg(tipmsg.r, option.tipType, {
						obj: M, type: 2 }, "hide");
				}//Endif
			});
			//subform
			var subform = function() {
				var flag = true;
				if(posting) return false;
				T.find("[dataType]").each(function() {
					var M = $(this);
					if(!(flag = $.fn.validform.sn.checkform(M, T, option.tipType))) {
						errorobj.focus();
						return false;
					}//Endif
					if(typeof(flag)!="boolean") {
						return (flag = true);
					}//Endif
					if(!(flag = $.fn.validform.sn.regcheck(M.attr("dataType"), M.val()))) {
						if(M.attr("ignore") === "ignore"
							&& (M.val() === "" || M.val() === M.attr("tipInfo"))) {
							return (flag = true);
						}//Endif
						(errorobj = M).focus();
						$.fn.validform.sn.showmsg(
							 M.attr("errTip") || tipmsg.w, option.tipType, { obj: $(this) });
						return false;
					}//Endif
					if(M.attr("ajaxurl")) {
						if(M.attr("valid") != "true") {
							flag = false;
							var thisobj = M;
							(errorobj = thisobj).focus();
							$.fn.validform.sn.showmsg(thisobj.attr("valid") || tipmsg.v,
								option.tipType, { obj: thisobj });
							(msghidden || option.tipType == 2) && setTimeout(function() {
								thisobj.trigger("blur");
							},2000);
							return false;
						}else {
							$.fn.validform.sn.showmsg(tipmsg.r,
								option.tipType, { obj: M, type: 2 },"hide");
							flag = true;
						}//Endif
					}//Endif
				});
				if(flag && !posting) {
					errorobj = null;
					option.postonce && (posting = true);
					if(!option.ajaxPost) {
						T.get(0).submit();
						return;
					}//Endif
					//传入“alwaysshow”则让提示框不管当前tiptye为1还是2都弹出
					$.fn.validform.sn.showmsg(
						tipmsg.p, option.tipType, { obj: $(this) }, "alwaysshow");
					$.ajax({
						type: "POST",
						dataType:"json",
						url: T.attr("action"),
						data: T.serialize(),
						success: function(data) {
							$.fn.validform.sn.showmsg(
								data.info,option.tipType, { obj: $(this) }, "alwaysshow");
							option.callback && option.callback(data);
						}
					});
					return false;
				}//Endif
			};
			option.btnSubmit && T.find(option.btnSubmit).bind("click", subform);
			T.submit(function() {
				subform();
				return false;
			});
		});
		//预创建pop box;
		(option.tipType != 2 || option.ajaxurl) && creatMsgbox();
	};
	$.fn.validform.sn = {
		defaults: {
			tipType: 1, ajaxPost: false
		},
		regcheck: function(type, gets, reg) {
			switch(type) {
				case "*":
					return true;
				case "*6-16":
					reg= /^[^\s]{6,16}$/;
					return reg.test(gets);
				case "n":
					return !isNaN(gets);
				case "s":
					return isNaN(gets);
				case "s5-16":
					reg= /^[\u4E00-\u9FA5\uf900-\ufa2d\w]{5,16}$/;
					return reg.test(gets);
				case "s6-18":
					reg= /^[\u4E00-\u9FA5\uf900-\ufa2d\w]{6,18}$/;
					return reg.test(gets);
				case "p":
					reg= /^[0-9]{6}$/;
					return reg.test(gets);
				case "m":
					reg= /^13[0-9]{1}[0-9]{8}$|15[0189]{1}[0-9]{8}$|18[2689]{1}[0-9]{8}$/;
					return reg.test(gets);
				case "e":
					reg = /\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/;
					return reg.test(gets);
				case "strength":
					return getPasswordStrength(gets) > 2;
				default:
					return false;
			}
		},
		showmsg: function(msg, type, o, show) {
			//o:{obj: 当前对象, type: 1=>正在检测 | 2=>通过}, show用来判断tipType=1的情况下是否弹出信息框;
			errorobj && errorobj.addClass("validform_error");
			(type == 1 || show == "alwaysshow")
				&& msgobj.find(".validform_info").text(msg);
			if(type == 1 && show != "hide" || show == "alwaysshow") {
				msghidden = false;
				msgobj.find(".iframe").css("height", msgobj.height());
				var w = $(window), d = document, dd = d.documentElement,
					t = (w.height()-msgobj.height()) / 2;
				msgobj.css({
					left: (w.width() - msgobj.width()) / 2
				}).show().animate({
					top: (dd.scrollTop ? dd.scrollTop : d.body.scrollTop) + (t > 0 ? t : 0)
				},100);
			}else if(type == 2) {
				if(o.type) {
					switch(o.type) {
						case 1:
							//正在检测;
							o.obj.parent().next().find(".validform_checktip")
								.removeClass().addClass("validform_checktip validform_loading").text(msg);
							break;
						case 2:
							//检测通过;
							o.obj.parent().next().find(".validform_checktip")
								.removeClass().addClass("validform_checktip validform_right").text(msg);
					}//Endswitch
				}else {
					o.obj.parent().next().find(".validform_checktip")
						.removeClass().addClass("validform_wrong validform_checktip").text(msg);
				}//Endif
			}//Endif
		},
		checkform: function(obj, parentobj, tipType, show) {
			//show用来判断是表达提交还是blur事件引发的检测
			var errTip = obj.attr("errTip") || tipmsg.w;
			if(obj.is("[dataType='radio']")) {
				//判断radio表单元素
				var inputname = obj.attr("name"),
					radiovalue = parentobj.find(":radio[name=" + inputname + "]:checked").val();
				if(!radiovalue) {
					errorobj = obj;
					this.showmsg(errTip,tipType, { obj: obj }, show);
					return false;
				}//Endif
				errorobj = null;
				this.showmsg(tipmsg.r, tipType, { obj: obj, type: 2 }, "hide");
				return "radio";
			}//Endif
			if(obj.is("[dataType='checkbox']")) {
				//判断checkbox表单元素
				var inputname = obj.attr("name"),
					checkboxvalue = parentobj
						.find(":checkbox[name=" + inputname + "]:checked").val();
				if(!checkboxvalue) {
					errorobj = obj;
					this.showmsg(errTip, tipType, { obj: obj }, show);
					return false;
				}//Endif
				errorobj = null;
				this.showmsg(tipmsg.r, tipType, { obj: obj, type: 2 }, "hide");
				return "checkbox";
			}//Endif
			if(obj.is("[dataType='select']")) {
				//判断select表单元素;
				if(!obj.val()) {
					errorobj = obj;
					this.showmsg(errTip,tipType, { obj: obj }, show);
					return false;
				}//Endif
				errorobj = null;
				this.showmsg(tipmsg.r, tipType, { obj: obj, type:2 }, "hide");
				return "select";
			}//Endif
			var defaultvalue = obj.attr("tipInfo");
			if((obj.val() === "" || obj.val() === defaultvalue)
				&& obj.attr("ignore") != "ignore") {
				errorobj = obj;
				this.showmsg(obj.attr("nullmsg") || tipmsg.s, tipType, { obj: obj }, show);
				return false;
			}//Endif
			if(obj.attr("recheck")) {
				var theother = parentobj
						.find("input[name=" + obj.attr("recheck") + "]:first");
				if(obj.val() != theother.val()) {
					errorobj = obj;
					this.showmsg(errTip, tipType, { obj: obj }, show);
					return false;
				}//Endif
			}//Endif
			obj.removeClass("validform_error");
			errorobj = null;
			return true;
		}
	};
	//公用方法显示&关闭信息提示框;
	$.Showmsg= function(msg) {
		creatMsgbox();
		$.fn.validform.sn.showmsg(msg, 1);
	};
	$.Hidemsg = function() {
		msgobj.hide();
		msghidden = true;
	};
})(jQuery);
